# -*-coding:utf-8-*-
import re

from django.conf import settings
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings

from users.models import User
from verifications.views import SMSCodeView
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
from celery_tasks.email.tasks import send_verify_email


class UserSerializer(serializers.ModelSerializer):
    """
    保存用户的序列化器
        allow: "true"
        mobile: "13711111111"
        password: "11111111"
        password2: "11111111"
        sms_code: "261800"
        username: "python"
    """# 对模型类中没有的字段仅进行反序列化输入
    password2 = serializers.CharField(max_length=20, min_length=8, write_only=True)
    sms_code = serializers.CharField(max_length=6, min_length=6, write_only=True)
    allow = serializers.CharField(write_only=True)

    class Meta:
        model = User
        fields = ("id", "username", "mobile", "password", "password2", "sms_code", "allow")
        extra_kwargs = {
            # 对模型类中的字段添加规则
            "password":{
                "write_only": True,
                "max_length":20,
                "min_length":8
            },
            "username":{
                "max_length":20,
                "min_length":5
            }
        }

    def validated_mobile(self, value):
        """
        验证手机好格式
        :param value:
        :return:
        """
        if not re.match(r"1[3-9]\d{9}", value):
            raise serializers.ValidationError("手机号格式不正确")
        return value

    def validated_allow(self, value):
        """
        验证是否同意协议
        :param value:
        :return:
        """
        if value != "true":
            raise serializers.ValidationError("未同意协议")
        return value

    def validate(self, attrs):
        """
        验证密码和短信验证码
        :param attrs:
        :return:
        """
        # 验证密码
        if attrs["password"] != attrs["password2"]:
            raise serializers.ValidationError("两次密码不一致")

        # 短信验证码
        real_sms_code = SMSCodeView.checkSMSCode(attrs["mobile"])
        if real_sms_code is None:
            raise serializers.ValidationError("短信验证码过期")
        if real_sms_code != attrs["sms_code"]:
            raise serializers.ValidationError("短信验证码错误")

        return attrs


    def create(self, validated_data):
        """
        保存用户数据
        :param validated_data:
        :return:
        """
        # 1.删除无用数据 ==> 字典删除
        del validated_data["sms_code"]
        del validated_data["password2"]
        del validated_data["allow"]
        print("保存用户数据: %s" % validated_data)

        # 保存,使用模型累的管理器方法
        user = User.objects.create_user(**validated_data)
        # user = super().create(validated_data)

        # 生成token,实现状态保持
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)  # 生成载荷
        token = jwt_encode_handler(payload)  # 生成token
        user.token = token

        # 3.将保存的数据返回
        return user


class UserDetailSerializer(serializers.ModelSerializer):
    """用户详情信息序列化器"""
    # 直接序列化模型数据
    class Meta:
        model = User
        fields = ("id", "username", "mobile", "email", "email_active")


class EmailSerializer(serializers.ModelSerializer):
    """保存邮箱序列化器"""
    class Meta:
        model = User
        fields = ('id', 'email')
        extra_kwargs = {
            'email':{
                'required':True # 是否必传
            }
        }


    def update(self, instance, validated_data):
        """
        更新邮箱到用户字段
        :param instance:
        :param validated_data:
        :return:
        """
        instance.email = validated_data["email"]
        instance.save()
        # 生成验证url
        verify_url = self.generate_verify_email_url(instance)
        email = instance.email
        # 异步发送邮件
        send_verify_email.delay(email, verify_url)
        return instance

    def generate_verify_email_url(self,instance):
        """
        生成验证邮箱的url
        :return:
        """
        tjs = TJS(settings.SECRET_KEY, 300)
        token = tjs.dumps({"username":instance.username}).decode()
        verify_url = 'http://www.meiduo.site:8080/success_verify_email.html?token=' + token
        return verify_url





